import org.junit.Test;

import java.util.*;


/**
 * 从传统方式到java8lambda表达式对以下需求的实现案例
 * 本demo中用到了策略模式
 * 需求1：获取当前公司中员工年龄大于35的员工
 * 需求2：获取当前公司中员工工资大于10000的员工信息
 */

public class TestOne {

    /***
     * java8之前,比较对象，使用匿名内部类
     */

    @Test
    public void testOne(){
        //匿名内部类
        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);//有用的核心代码就这一句
            }
        };

        TreeSet<Integer> treeSet = new TreeSet<>(comparator);
    }

    //Lambda 表达式解决上面的问题
    @Test
    public void test2(){
        Comparator<Integer> comparator = (x,y) -> Integer.compare(x,y);

        TreeSet<Integer> treeSet = new TreeSet<>(comparator);
    }

    //先来个Employes对象的集合
    List<Employee> employees = Arrays.asList(
            new Employee("张三",22,87979.45),
            new Employee("李四",35,63497.96),
            new Employee("王五",18,3200.21),
            new Employee("赵六",28,197979.58),
            new Employee("田七",30,297979.22)
    );

    /**
     * 需求1：获取当前公司中员工年龄大于35的员工
     */

    //传统的集合过滤规则
    public List<Employee> filterEmployees(List<Employee> list){
        List<Employee> emps = new ArrayList<>();
        for (Employee emp: list) {
            if(emp.getAge() >= 30){
                emps.add(emp);
            }
        }
        return emps;
    }

    /**
     * 传统方式过滤测试A
     */
    @Test
    public void testA(){
        List<Employee> list = filterEmployees(employees);
        for (Employee emp: list) {
            System.out.println(emp);
        }
    }


    //需求2：获取当前公司中员工工资大于10000的员工信息
    //传统的集合过滤规则
    public List<Employee> filterEmployees2(List<Employee> list){
        List<Employee> emps = new ArrayList<>();
        for (Employee emp: list) {
            if(emp.getSalary() >= 10000){//其实就改了这句，写了太多冗余的代码
                emps.add(emp);
            }
        }
        return emps;
    }

    /**
     * 传统方式过滤测试A
     */
    @Test
    public void testB(){
        List<Employee> list = filterEmployees(employees);
        for (Employee emp: list) {
            System.out.println(emp);
        }
    }




    /**
     * 优化方式一： 优化需求1与需求2过滤规则：使用设计模式(策略模式),给什么策略就按什么策略过滤
     * 缺点是，每次按给定策略过滤时，都需要写一个策略的实现类
     * @param list
     * @param myPredicate
     * @return
     */
    public List<Employee> filterEmployee(List<Employee> list,MyPredicate<Employee> myPredicate){
        List<Employee> employees = new ArrayList<>();
        for (Employee emp: list) {
            if (myPredicate.test(emp)){
                employees.add(emp);
            }
        }
        return employees;
    }

    //优化方式1测试：优化需求1与需求2：使用设计模式(策略模式)_测试
    @Test
    public void testAA(){
        //年龄大于30的员工信息
        List<Employee> employees = filterEmployee(this.employees, new FilterEmployeeByAge());
        for (Employee emp: employees) {
            System.out.println(emp);
        }
        System.out.println("---------------------------------------------------------------------------");
        //工资大于10000的员工信息
        List<Employee> employees2 = filterEmployee(this.employees, new FilterEmployeeBySalary());
        for (Employee emp: employees2) {
            System.out.println(emp);
        }
    }

    //优化方式2：使用匿名内部类,结合设计模式(策略模式)

    @Test
    public void test5(){
       List<Employee> employeeList = filterEmployee(employees, new MyPredicate<Employee>() {
            @Override
            public boolean test(Employee employee) {
                return employee.getAge()>30;
            }
        });

        for (Employee emp: employeeList) {
            System.out.println(emp);
        }
    }

    /***
     * 优化方式3： lambda 表达式
     */
    @Test
    public void test6(){
        List<Employee> employees = filterEmployee(this.employees, (e) -> e.getAge() >= 30);
        employees.forEach(System.out :: println);
    }

    /**
     * 优化方式4：Stream API
     */

    @Test
    public void test7(){
        employees.stream().filter((e) -> e.getSalary() >= 10000).forEach(System.out::println);

        employees.stream().map(Employee::getName).forEach(System.out::println);
    }
}
